package com.lngsyz.file.util;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.lngsyz.file.exception.RequestSystemException;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class ImageUtil {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(ImageUtil.class);

	/**
	 * 
	 * @param base64Str
	 * @param maxSize  单位B  如果32KB，32000
	 * @return
	 */
	public static String compressUnderSize(String base64Str, long maxSize) {
		if(StringUtils.isNotBlank(base64Str)) {
			byte[] imgBytes = base64ToByte(base64Str);
			byte[] compressImgBytes = compressUnderSize(imgBytes, maxSize);
			String compressImgBase64 = byte2Base64StringFun(compressImgBytes);
			return compressImgBase64;
		} else {
			return "";
		}
	}

	//base64字符串转byte[]
    public static byte[] base64ToByte(String base64Str){
        return Base64.decodeBase64(base64Str);
    }

    //byte[]转base64
    public static String byte2Base64StringFun(byte[] b){
        return Base64.encodeBase64String(b);
    }

    /**
     * 将图片压缩到指定大小以内
     * 
     * @param srcImgData 源图片数据
     * @param maxSize 目的图片大小
     * @return 压缩后的图片数据
     */
    public static byte[] compressUnderSize(byte[] srcImgData, long maxSize) {
        double scale = 0.9;
        byte[] imgData = Arrays.copyOf(srcImgData, srcImgData.length);
 
        if (imgData.length > maxSize) {
            do {
                try {
                    imgData = compress(imgData, scale);
                } catch (Exception e) {
                	LOGGER.error("业务异常信息：[{}]", e.getMessage(), e);
                    throw new IllegalStateException("压缩图片过程中出错，请及时联系管理员！", e);
                }
 
            } while (imgData.length > maxSize);
        }
 
        return imgData;
    }
 
    /**
     * 按照 宽高 比例压缩
     * 
     * @param imgIs 待压缩图片输入流
     * @param scale 压缩刻度
     * @param out 输出
     * @return 压缩后图片数据
     * @throws IOException 压缩图片过程中出错
     */
    public static byte[] compress(byte[] srcImgData, double scale) throws IOException {
    	ByteArrayOutputStream bOut = null;
    	try {
    		BufferedImage bi = ImageIO.read(new ByteArrayInputStream(srcImgData));
	        int width = (int) (bi.getWidth() * scale); // 源图宽度
	        int height = (int) (bi.getHeight() * scale); // 源图高度
	 
//	        Image image = bi.getScaledInstance(width, height, Image.SCALE_SMOOTH);
//	        BufferedImage tag = tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//	 
//	        Graphics g = tag.getGraphics();
//	        g.setColor(Color.RED);
//	        g.drawImage(image, 0, 0, null); // 绘制处理后的图
//	        g.dispose();
//	 
//	        bOut = new ByteArrayOutputStream();
//	        ImageIO.write(tag, "JPEG", bOut);
// 			return bOut.toByteArray();
	        
	        
	        BufferedImage to = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			Graphics2D g2d = to.createGraphics();
			to = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
			g2d.dispose();
			g2d = to.createGraphics();
			@SuppressWarnings("static-access")
			Image from = bi.getScaledInstance(width, height, bi.SCALE_AREA_AVERAGING);
			g2d.drawImage(from, 0, 0, null);
			g2d.dispose();
			bOut = new ByteArrayOutputStream();
			ImageIO.write(to, "png", bOut);
	        
	        return bOut.toByteArray();
    	} catch (IOException e) {
            LOGGER.error("业务异常信息：[{}]", e.getMessage(), e);
            throw e;
        } finally {
            try {
            	bOut.close();
            } catch (IOException e) {
                LOGGER.error("业务异常信息：[{}]", e.getMessage(), e);
            }
        }
    }

    /**
     * base64 转图片
     * @param base64ImgData
     * @param filePath
     * @throws IOException
     */
	public static void convertBase64ToImage(String base64ImgData, String filePath) {
		try {
			BASE64Decoder d = new BASE64Decoder();
			byte[] bs = d.decodeBuffer(base64ImgData);
			FileOutputStream os = new FileOutputStream(filePath);
			os.write(bs);
			os.close();
		} catch(Exception e) {
			LOGGER.error("业务异常信息：[{}]", e.getMessage(), e);
		}
	}

	/**
	 * 图片转base64
	 * @param imgFile
	 * @return
	 */
	public static String convertImageToBase64(String imgFile) {// 将图片文件转化为字节数组字符串，并对其进行Base64编码处理
		if(StringUtils.isNotBlank(imgFile)) {
			try {
				byte[] data;
				data = getImage(imgFile);
				// 对字节数组Base64编码
				BASE64Encoder encoder = new BASE64Encoder();
				return encoder.encode(data);// 返回Base64编码过的字节数组字符串
			} catch (Exception e) {
				// TODO Auto-generated catch block
				LOGGER.error("业务异常信息：[{}]", e.getMessage(), e);
			}
			return "";
		} else {
			return "";
		}
	}
	
	private static byte[] getImage(String filePath) throws Exception {
		File f = new File(filePath);
        if (!f.exists()) {
            throw new FileNotFoundException(filePath);
        }
 
        ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length());
        BufferedInputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(f));
            int buf_size = 1024;
            byte[] buffer = new byte[buf_size];
            int len = 0;
            while (-1 != (len = in.read(buffer, 0, buf_size))) {
                bos.write(buffer, 0, len);
            }
            return bos.toByteArray();
        } catch (IOException e) {
            LOGGER.error("业务异常信息：[{}]", e.getMessage(), e);
            throw e;
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                LOGGER.error("业务异常信息：[{}]", e.getMessage(), e);
            }
            bos.close();
        }
    }

	/**
	 * 印模图去白色底色
	 * @param img
	 * @return
	 */
	public static byte[] transfer2Byte(byte[] img) {
        ByteArrayOutputStream byteArrayOutputStream = null;
        InputStream is = null;
        byte[] result = null;
        try {
            is = new ByteArrayInputStream(img);
            BufferedImage bi = ImageIO.read(is);
            ImageIcon imageIcon = new ImageIcon(bi);
            BufferedImage bufferedImage = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(),
                    BufferedImage.TYPE_4BYTE_ABGR);
            Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics();
            g2D.drawImage(imageIcon.getImage(), 0, 0, imageIcon.getImageObserver());
            int alpha = 0;
            for (int j1 = bufferedImage.getMinY(); j1 < bufferedImage.getHeight(); j1++) {
                for (int j2 = bufferedImage.getMinX(); j2 < bufferedImage.getWidth(); j2++) {
                    int rgb = bufferedImage.getRGB(j2, j1);
 
                    int R = (rgb & 0xff0000) >> 16;
                    int G = (rgb & 0xff00) >> 8;
                    int B = (rgb & 0xff);
                    if (((255 - R) < 120) && ((255 - G) < 120) && ((255 - B) < 120)) {
                        rgb = ((alpha + 1) << 24) | (rgb & 0x00ffffff);
                    } else {
                    	// 如果不是透明，修改颜色为红色
                    	if(rgb != 0x00000000) {
                    		rgb = Color.red.getRGB();
                    	}
                    }
                    bufferedImage.setRGB(j2, j1, rgb);
                }
            }
            g2D.drawImage(bufferedImage, 0, 0, imageIcon.getImageObserver());
            byteArrayOutputStream = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "png", byteArrayOutputStream);//转换成byte数组
            result = byteArrayOutputStream.toByteArray();
        } catch (Exception e) {
            // TODO Auto-generated catch block
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                }
            }
            if (byteArrayOutputStream != null) {
                try {
                    byteArrayOutputStream.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                }
            }
        }
        return result;
    }
	
	private static byte[] fileToByteArray(File file) {
        byte[] byteArray = null;
        try (FileInputStream fis = new FileInputStream(file);
             ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            byteArray = bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return byteArray;
    }
	
	public static void writeBytes(byte[] data, String filePath) {
		try (FileOutputStream fos = new FileOutputStream(filePath)) {
            fos.write(data); // 将byte数组写入文件
        } catch (IOException e) {
            e.printStackTrace();
        }
	}
	
	public static byte[] base64OrUrlToLocal(String base64OrUrl) throws Exception {
		if(StringUtils.isNotBlank(base64OrUrl)) {
			if(StringUtils.startsWith(base64OrUrl, "http")) {
				return HttpUtils.download(base64OrUrl);
			} else {
				return ImageUtil.base64ToByte(base64OrUrl);
			}
		} else {
			throw new RequestSystemException("参数不可为空");
		}
	}
	
	public static byte[] generateQRCodeBytes(String qrCodeText, int width, int height) throws Exception {
    	// 生成二维码图像
    	QRCodeWriter qrCodeWriter = new QRCodeWriter();
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.MARGIN, 0); // 设置边距为0，即无白边；如果设置值，会有边距白边
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");	// 解决中文乱码
        BitMatrix bitMatrix =  qrCodeWriter.encode(qrCodeText, BarcodeFormat.QR_CODE, width, height, hints);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        MatrixToImageWriter.writeToStream(bitMatrix, "PNG", baos);
        return baos.toByteArray();
    }
	
	/**
     * 读取资源图片文件并返回其内容的Base64编码字符串
     * @param resourcePath 资源图片文件的路径
     * @return Base64编码的字符串，如果文件不存在则返回null
     */
    public static String readResourceImageAsBase64(String resourcePath) {
        // 获取当前类的类加载器
        ClassLoader classLoader = ImageUtil.class.getClassLoader();
        
        // 使用类加载器获取资源图片文件的输入流
        try (InputStream inputStream = classLoader.getResourceAsStream(resourcePath)) {
            // 检查输入流是否为空
            if (inputStream == null) {
                System.out.println("图片未找到！");
                return null;
            }
            
            // 创建一个字节输出流来存储读取的数据
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            int nRead;
            byte[] data = new byte[1024]; // 缓冲区大小
            
            // 从输入流中读取数据到缓冲区，然后写入字节输出流
            while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
                buffer.write(data, 0, nRead);
            }
            
            // 将字节输出流转换为字节数组
            byte[] imageBytes = buffer.toByteArray();
            
            // 使用Base64编码工具将字节数组转换为Base64字符串
            return java.util.Base64.getEncoder().encodeToString(imageBytes);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
	
	public static void main(String args[]) {
		// 调用方法读取图片文件内容并转换为Base64字符串
        String base64Content = ImageUtil.readResourceImageAsBase64("img/img.png");
        
        if (base64Content != null) {
            System.out.println("图片读取成功，Base64内容：" + base64Content);
        } else {
            System.out.println("图片未找到或读取失败！");
        }
		
		
//		String filePath = "c:/img/randomCode/1.png";
//		String destFilePath = "c:/img/randomCode/2.png";
//		String base64Str = convertImageToBase64(filePath);
//		String compressBase64Str = compressUnderSize(base64Str, 3000);
//		convertBase64ToImage(compressBase64Str, destFilePath);
		
		// 去白色底色
		byte[] originalBytes = fileToByteArray(new File("C:/Users/12336/Desktop/test/ygg01.png"));
		originalBytes = transfer2Byte(originalBytes);
//		byte[] compressBytes = compressUnderSize(originalBytes, 30000);
        writeBytes(originalBytes, "D:/GC/sss.png");
	}
}
